﻿using System;
using System.IO;
using System.Text.RegularExpressions;
using YanZhiwei.DotNet2.Utilities.Base;
using YanZhiwei.DotNet2.Utilities.Models;
namespace YanZhiwei.DotNet2.Utilities.Common
{
    /// <summary>
    /// 参数验证帮助类
    ///<para>参考：http://www.dotblogs.com.tw/kirkchen/archive/2010/03/04/13887.aspx?fid=54791 </para> 
    /// </summary>
    public static class ValidateHelper
    {
        #region 验证初始化
        /// <summary>
        /// 验证初始化
        /// </summary>
        /// <returns></returns>
        public static Validation Begin()
        {
            return null;
        }
        #endregion
        #region 参数验证
        private static Validation Check<TException>(this Validation validation, Func<bool> filterMethod, string message) where TException : Exception
        {
            if (filterMethod())
            {
                return validation ?? new Validation() { IsValid = true };
            }
            else
            {
                TException _exception = (TException)Activator.CreateInstance(typeof(TException), message);
                throw _exception;
            }
        }
        ///// <summary>
        ///// 参数验证
        ///// </summary>
        ///// <param name="validation">Validation</param>
        ///// <param name="filterMethod">返回BOOL类型的委托</param>
        ///// <param name="argumentName">参数名称</param>
        ///// <returns>Validation</returns>
        //public static Validation Check(this Validation validation, Func<bool> filterMethod, string argumentName)
        //{
        //    return Check<Exception>(validation, filterMethod, new ArgumentException("参数无效.", argumentName));
        //}
        #endregion
        #region 验证非空
        /// <summary>
        /// 验证非空
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">输入项</param>
        /// <param name="paramName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation NotNull(this Validation validation, Object data, string paramName)
        {
            return Check<ArgumentNullException>(
                validation,
                () => CheckHelper.NotNull(data),
                string.Format(Resource.ParameterCheck_NotNull, paramName)
            );
        }
        #endregion
        #region 不能为空或者NULL验证
        /// <summary>
        /// 不能为空或者NULL验证
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="input">输入项</param>
        /// <param name="paramName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation NotNullOrEmpty(this Validation validation, string input, string paramName)
        {
            return Check<ArgumentNullException>(
             validation,
             () => !string.IsNullOrEmpty(input),
             string.Format(Resource.ParameterCheck_NotNullOrEmpty_Collection, paramName)
         );
        }
        #endregion
        #region 验证参数不能等于某个值
        /// <summary>
        /// 验证参数不能等于某个值
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">输入项</param>
        /// <param name="equalObj">比较项</param>
        /// <param name="paramName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation NotEqual(this Validation validation, object data, object equalObj, string paramName)
        {
            return Check<ArgumentException>(
                validation,
                () => data != equalObj,
                string.Format(Resource.ParameterCheck_NotEqual, paramName, data)//string.Format("参数名：'{0}'的值不能等于'{1}'.", argumentName, obj))
            );
        }
        #endregion
        #region 验证是否在范围内
        /// <summary>
        /// 验证是否在范围内
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">输入项</param>
        /// <param name="min">最小值</param>
        /// <param name="max">最大值</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation InRange(this Validation validation, string data, int min, int max, string argumentName)
        {
            return Check<ArgumentOutOfRangeException>(
                validation,
                () => CheckHelper.InRange(data, min, max),
                string.Format(Resource.ParameterCheck_Between, min, max)
            );
        }
        #endregion
        #region 需要验证的正则表达式
        /// <summary>
        /// 需要验证的正则表达式
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="input">需要匹配的输入项</param>
        /// <param name="pattern">正则表达式</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation RegexMatch(this Validation validation, string input, string pattern, string argumentName)
        {
            return Check<ArgumentException>(
                validation,
                () => Regex.IsMatch(input, pattern),
                string.Format(Resource.ParameterCheck_Match, input, argumentName)
            );
        }
        /// <summary>
        /// 需要验证的正则表达式
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="checkFactory">委托</param>
        /// <param name="pattern">正则表达式</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation RegexMatch(this Validation validation, Func<bool> checkFactory, string pattern, string argumentName)
        {
            return Check<ArgumentException>(
                validation,
                checkFactory,
                string.Format(Resource.ParameterCheck_Match2, argumentName)
            );
        }
        #endregion
        #region 是否是电子邮箱
        /// <summary>
        /// 是否是电子邮箱
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="email">需要验证的邮箱</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsEmail(this Validation validation, string email, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsEmail(email), RegexPattern.EmailCheck, argumentName);
            //return RegexMatch(validation, email, RegexPattern.EmailCheck, argumentName);
        }
        #endregion
        #region 是否是URL
        /// <summary>
        /// 是否是URL
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">url</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsURL(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsURL(data), RegexPattern.URLCheck, argumentName);
            //return RegexMatch(validation, url, RegexPattern.URLCheck, argumentName);
        }
        #endregion
        #region 是否是文件路径
        /// <summary>
        /// 是否是文件路径
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">路径</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsFilePath(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsFilePath(data), RegexPattern.URLCheck, argumentName);
            // return RegexMatch(validation, path, RegexPattern.FileCheck, argumentName);
        }
        #endregion
        #region 是否是邮政编码
        /// <summary>
        /// 是否是邮政编码
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">邮政编码</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsPoseCode(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsPoseCode(data), RegexPattern.PostCodeCheck, argumentName);
            //return RegexMatch(validation, poseCode, RegexPattern.PostCodeCheck, argumentName);
        }
        #endregion
        #region 是否是IP
        /// <summary>
        /// 是否是IP
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">需要检测到IP</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsIp(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsIp(data), RegexPattern.IpCheck, argumentName);
            //return RegexMatch(validation, ip, RegexPattern.IpCheck, argumentName);
        }
        #endregion
        #region 是否是整数
        /// <summary>
        /// 是否是整数
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">需要检测的字符串</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsInt(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsInt(data), RegexPattern.IntCheck, argumentName);
            //return RegexMatch(validation, intString, RegexPattern.IntCheck, argumentName);
        }
        #endregion
        #region 是否是数字
        /// <summary>
        /// 是否是数字
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">需要检测的字符串</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsNumber(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsNumber(data), RegexPattern.NumberCheck, argumentName);
            // return RegexMatch(validation, numberString, RegexPattern.NumberCheck, argumentName);
        }
        #endregion
        #region 是否是中文
        /// <summary>
        /// 是否是中文
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">中文</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsChinses(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsChinses(data), RegexPattern.ChineseCheck, argumentName);
            //return RegexMatch(validation, data, RegexPattern.ChineseCheck, argumentName);
        }
        #endregion
        #region 是否是身份证号码
        /// <summary>
        /// 是否是身份证号码
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">验证数据</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsIdCard(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsIdCard(data), RegexPattern.IdCardCheck, argumentName);
            //   return RegexMatch(validation, data, RegexPattern.IdCardCheck, argumentName);
        }
        #endregion
        #region 判断字符串是否是要求的长度
        /// <summary>
        /// 判断字符串是否是要求的长度
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="input">验证的字符串</param>
        /// <param name="requireLength">要求的长度</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsRequireLen(this Validation validation, string input, int requireLength, string argumentName)
        {
            return Check<ArgumentException>(
               validation,
               () => input.Length == requireLength,
               string.Format(Resource.ParameterCheck_StringLength, argumentName, requireLength));
        }
        #endregion
        #region 是否是十六进制字符串
        /// <summary>
        /// 是否是十六进制字符串
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">验证数据</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation</returns>
        public static Validation IsHexString(this Validation validation, string data, string argumentName)
        {
            return RegexMatch(validation, () => CheckHelper.IsHexString(data), RegexPattern.HexStringCheck, argumentName);
        }
        #endregion
        #region 检查参数必须小于[或可等于，参数canEqual]指定值，
        /// <summary>
        /// 检查参数必须小于[或可等于，参数canEqual]指定值，否则抛出<see cref="ArgumentOutOfRangeException"/>异常。
        /// </summary>
        /// <typeparam name="T">参数类型。</typeparam>
        /// <param name="validation">Validation</param>
        /// <param name="value"></param>
        /// <param name="paramName">参数名称。</param>
        /// <param name="target">要比较的值。</param>
        /// <param name="canEqual">是否可等于。</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static void CheckLessThan<T>(this Validation validation, T value, string paramName, T target, bool canEqual) where T : IComparable<T>
        {
            string _format = canEqual ? Resource.ParameterCheck_NotLessThanOrEqual : Resource.ParameterCheck_NotLessThan;
            Check<ArgumentOutOfRangeException>(validation, () => canEqual ? value.CompareTo(target) <= 0 : value.CompareTo(target) < 0, string.Format(_format, paramName, target));
        }
        #endregion
        #region 检查参数必须大于[或可等于，参数canEqual]指定值
        /// <summary>
        /// 检查参数必须大于[或可等于，参数canEqual]指定值，否则抛出<see cref="ArgumentOutOfRangeException"/>异常。
        /// </summary>
        /// <typeparam name="T">参数类型。</typeparam>
        /// <param name="validation">Validation</param>
        /// <param name="value"></param>
        /// <param name="paramName">参数名称。</param>
        /// <param name="target">要比较的值。</param>
        /// <param name="canEqual">是否可等于。</param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static void CheckGreaterThan<T>(this Validation validation, T value, string paramName, T target, bool canEqual) where T : IComparable<T>
        {
            // bool flag = canEqual ? value.CompareTo(target) >= 0 : value.CompareTo(target) > 0;
            string _format = canEqual ? Resource.ParameterCheck_NotGreaterThanOrEqual : Resource.ParameterCheck_NotGreaterThan;
            Check<ArgumentOutOfRangeException>(validation, () => canEqual ? value.CompareTo(target) >= 0 : value.CompareTo(target) > 0, string.Format(_format, paramName, target));
        }
        #endregion
        #region  检查指定路径的文件夹必须存在
        /// <summary>
        /// 检查指定路径的文件夹必须存在，否则抛出<see cref="DirectoryNotFoundException"/>异常。
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="directory"></param>
        /// <param name="paramName">参数名称。</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="DirectoryNotFoundException"></exception>
        public static void CheckDirectoryExists(this Validation validation, string directory, string paramName = null)
        {
            Check<DirectoryNotFoundException>(validation, () => Directory.Exists(directory), string.Format(Resource.ParameterCheck_DirectoryNotExists, directory));
        }
        #endregion
        #region 检查指定路径的文件必须存在
        /// <summary>
        /// 检查指定路径的文件必须存在，否则抛出<see cref="FileNotFoundException"/>异常。
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="filename"></param>
        /// <param name="paramName">参数名称。</param>
        /// <exception cref="ArgumentNullException">当文件路径为null时</exception>
        /// <exception cref="FileNotFoundException">当文件路径不存在时</exception>
        public static void CheckFileExists(this Validation validation, string filename, string paramName)
        {
            Check<FileNotFoundException>(validation, () => File.Exists(filename), string.Format(Resource.ParameterCheck_FileNotExists, filename));
        }
        #endregion
    }
}